package com.fdb.efp.batch.service.impl.hjwp;

import com.fdb.basic.framework.core.bean.SedSynAccRepayPlayDetailVO;
import com.fdb.basic.framework.core.bean.TxtFileLoadBean;
import com.fdb.basic.framework.core.constant.BaseConstant;
import com.fdb.basic.framework.core.util.StringUtil;
import com.fdb.basic.framework.core.util.TimeUtil;
import com.fdb.basic.framework.core.util.TxtFileLoadPlugin;
import com.fdb.efp.batch.service.facade.hjwp.SynLoanRepayDetailProcessService;
import com.fdb.efp.console.common.ConsoleConstant;
import com.fdb.efp.console.service.facade.PrdInfoService;
import com.fdb.efp.console.service.facade.PubSysInfoService;
import com.fdb.efp.console.service.facade.SDicService;
import com.fdb.efp.loan.service.facade.AccLoanService;
import com.fdb.efp.loan.service.facade.LoanRepayDetailService;
import com.fdb.efp.loan.service.facade.LoanRepayPlanService;
import com.fdb.efp.loan.service.facade.SyncRepayDetailDiffLogService;
import com.fdb.efp.loan.service.vo.AccLoanVO;
import com.fdb.efp.loan.service.vo.LoanRepayDetailVO;
import com.fdb.efp.loan.service.vo.LoanRepayPlanVO;
import com.fdb.efp.loan.service.vo.SyncRepayDetailDiffLogVO;
import com.fdb.efp.nls.common.constant.NlsApplyInfoEnums;
import com.fdb.efp.nls.service.facade.NlsApplyInfoService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import java.io.File;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

import static com.fdb.basic.framework.core.util.BeanUtility.beanCopy;


/**
 * 互金晚批同步-还款记录同步
 */
@Service("synLoanRepayDetailProcessService")
public class SynLoanRepayDetailProcessServiceImpl implements SynLoanRepayDetailProcessService, SynFileDataInterface {
    /**
     * 日志
     */
    private static Logger logger = LoggerFactory.getLogger(SynLoanRepayDetailProcessServiceImpl.class);
    /**
     * 还款明细服务
     */
    @Autowired
    @Qualifier("loanRepayDetailService")
    private LoanRepayDetailService loanRepayDetailService;

    @Autowired
    @Qualifier("nlsApplyInfoService")
    private NlsApplyInfoService nlsApplyInfoService;

    @Autowired
    private SDicService sDicService;

    @Autowired
    private PrdInfoService prdInfoService;

    @Autowired
    private PubSysInfoService pubSysInfoService;

    private String openDay;

    @Autowired
    private SyncRepayDetailDiffLogService syncRepayDetailDiffLogService;

    private String batchSubDate;

    private Date batchRunDate;

    private ArrayList<SyncRepayDetailDiffLogVO> diffLogVOS = new ArrayList<>();

    /**
     * 台账服务
     */
    @Autowired
    @Qualifier("accLoanService")
    private AccLoanService accLoanService;

    @Autowired
    private LoanRepayPlanService loanRepayPlanService;

    private static final Map<String, String> repayType = new HashMap<>();

    static {
        //NS-正常回收,ER-提前回收,PO-清户,WV-豁免,PP-部分提前还款(收费),PF-提前结清收费,TR-终止
        //01 正常还款
        //02 提前部分还款
        //03 提前结清
        //04 逾期还款
        //05 代偿结清
        //06 按期次还款
        //07 欠款回收
        //08 结清
        //09 息费减免
        //10 部分还款

        //正常还款 1
        repayType.put("NS", ConsoleConstant.REPAY_TYPE_01);
        //提前部分还本1
        repayType.put("ER", ConsoleConstant.REPAY_TYPE_02);
        //部分还款（先还欠款如有剩余提前还本）--待定
        repayType.put("PR", ConsoleConstant.REPAY_TYPE_10);
        //按期次提前还款
        repayType.put("PS", ConsoleConstant.REPAY_TYPE_06);
        //结清1
        repayType.put("PO", ConsoleConstant.REPAY_TYPE_03);
        //利费减免1
        repayType.put("WV", ConsoleConstant.REPAY_TYPE_09);
    }

    @Override
    public Boolean synLoanRepayDetail(String sub_date_date) throws Exception {
        logger.info("批次时间：[{}]的互金还款记录同步批次开始运行", sub_date_date);
        batchSubDate = sub_date_date;
        batchRunDate = new Date();
        //查询当前的账务日期
        openDay = pubSysInfoService.getOpenday("1001");
        if (StringUtils.isEmpty(openDay)) {
            throw new Exception("获取openday为空");
        }
        logger.info("批次时间：[{}]的互金还款记录同步批次获取到的营业日期为：[{}]", sub_date_date, openDay);
        String fileUrl = sedLoanFilePath + getCurrentBatchFileName(fileNameOfDat, sub_date_date);
        if (!new File(fileUrl).exists()) {
            throw new RuntimeException("还款明细数据文件不存在,文件路径为：" + fileUrl);
        }
        //判断ok文件里面的数量是否为空
        if (getOkFileDataNum(sedLoanFilePath, fileNamOfOk, sub_date_date) < 1) {
            logger.info("批次时间：[{}]的互金还款记录同步批次获取到的ok文件(文件路径：[{}]；文件名：[{}])中的文件数据条数为空，本次批次结束", sub_date_date, sedLoanFilePath, fileNamOfOk);
            return Boolean.TRUE;
        }
        //校验ok文件
        boolean flag = validateOkFile(getFileNum(fileUrl), sedLoanFilePath, fileNamOfOk, sub_date_date);
        if (!flag) {
            logger.info("批次时间：[{}]的互金还款记录同步批次ok文件校验不通过", sub_date_date);
            return Boolean.FALSE;
        }
        TxtFileLoadPlugin txtFileLoadPlugin = new TxtFileLoadPlugin(fileUrl, "\u0002", "UTF-8", 0, 1000);
        List<TxtFileLoadBean> repayPlanList = txtFileLoadPlugin.run(new SynAccRepayPlayDetailVO());
        // 校验文件
        dueData(repayPlanList, sub_date_date);
        if (repayPlanList.size() != 0) {
            while (!repayPlanList.get(repayPlanList.size() - 1).isReadedComplete) {
                txtFileLoadPlugin.setFirstRead(false);
                repayPlanList = txtFileLoadPlugin.run(new SynAccRepayPlayDetailVO());
                if (repayPlanList.size() == 0) {
                    break;
                }
                dueData(repayPlanList, sub_date_date);
            }
        }
        return Boolean.TRUE;
    }


    private void dueData(List<TxtFileLoadBean> list, String sub_date_date) throws Exception {
        logger.info("批次时间：[{}]的互金还款记录同步批次执行dueData函数开始", sub_date_date);
        if (list == null) {
            return;
        }
        if (list.isEmpty()) {
            return;
        }
        diffLogVOS.clear();
        //获取互金传送的还款号集合
        List<String> setlSeqs = list.stream().map(e -> ((SynAccRepayPlayDetailVO) e).getRpyNo()).distinct().collect(Collectors.toList());
        //获取互金传送的还款流水对应的借据号集合
        List<String> loanNos = list.stream().map(e -> ((SynAccRepayPlayDetailVO) e).getLoanNo()).distinct().collect(Collectors.toList());

        //根据还款号 查询出本地的还款记录数据
        List<LoanRepayDetailVO> loanRepayDetailAs = loanRepayDetailService.queryByRpyNo(setlSeqs);
        if (loanRepayDetailAs == null) {
            loanRepayDetailAs = new ArrayList<>();
        }
        //根据借据号集合 查询对应的借据信息
        List<AccLoanVO> accLoanAs = accLoanService.queryByBillNos(loanNos);

        List<LoanRepayDetailVO> loanRepayDetailVOS = new ArrayList<>();

        for (TxtFileLoadBean txtFileLoadBean : list) {
            SynAccRepayPlayDetailVO sedSynAccRepayPlayDetailVO = (SynAccRepayPlayDetailVO) txtFileLoadBean;
            LoanRepayDetailVO loanRepayDetailVO = getByRpyNo(loanRepayDetailAs, sedSynAccRepayPlayDetailVO);
            if (Objects.isNull(loanRepayDetailVO)) {
                loanRepayDetailVO = new LoanRepayDetailVO();
                insertDiffLog("1", sedSynAccRepayPlayDetailVO, null);
            } else {
                //不是新增的数据，那么需要判断时间
                if (StringUtils.isNotEmpty(loanRepayDetailVO.getSetlValDt())) {
                    if (!SyncUtil.checkDate(loanRepayDetailVO.getSetlValDt(), openDay)) {
                        insertDiffLog("3", sedSynAccRepayPlayDetailVO, loanRepayDetailVO);
                        continue;
                    } else {
                        insertDiffLog("2", sedSynAccRepayPlayDetailVO, loanRepayDetailVO);
                    }
                }
            }
            beanCopy(sedSynAccRepayPlayDetailVO, loanRepayDetailVO);

            //如果主键为空，那么主键赋值为还款号
            if (StringUtils.isEmpty(loanRepayDetailVO.getSetlSeq())) {
                loanRepayDetailVO.setSetlSeq(sedSynAccRepayPlayDetailVO.getRpyNo());
            }
            //互金：还款方式
            setSetlType(sedSynAccRepayPlayDetailVO, loanRepayDetailVO);

            // 主动还款日期--回收日期 也就是bizdate
            if (StringUtils.isEmpty(loanRepayDetailVO.getSetlApplyDt())) {
                loanRepayDetailVO.setSetlApplyDt(sedSynAccRepayPlayDetailVO.getRetDate());
            }
            // 生效日期
            if (StringUtils.isEmpty(loanRepayDetailVO.getSetlValDt())) {
                loanRepayDetailVO.setSetlValDt(sedSynAccRepayPlayDetailVO.getRetDate());
            }
            //loanRepayDetailVO.setSetlValDt(sub_date_date);
            // 还款时总拖欠费用
            loanRepayDetailVO.setAllOdFeeAmt(BigDecimal.ZERO);
            // 归还费用总计
            loanRepayDetailVO.setSetlTotalFee(sedSynAccRepayPlayDetailVO.getSetlTotalFee());
            // 审批状态 赋值02
            loanRepayDetailVO.setWfApprSts(NlsApplyInfoEnums.NlsApplyState.PASS.getKey());
            loanRepayDetailVO.setRpSts("1");
            // 创建用户
            if (StringUtils.isEmpty(loanRepayDetailVO.getSetlCreateUsr())) {
                loanRepayDetailVO.setSetlCreateUsr(BaseConstant.ADMIN);
            }
            // 创建日期 取批次日期
            if (StringUtils.isEmpty(loanRepayDetailVO.getSetlCreateDt())) {
                loanRepayDetailVO.setSetlCreateDt(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
            }
            // 最新变更用户
            loanRepayDetailVO.setLastChgUsr(BaseConstant.ADMIN);
            // 最新变更时间
            loanRepayDetailVO.setLastChgDt(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));

            loanRepayDetailVOS.add(loanRepayDetailVO);

            String loanNo = loanRepayDetailVO.getLoanNo();
            AccLoanVO accLoanVO = accLoanAs.stream().filter(a -> a.getBillNo().equals(loanNo)).findFirst().orElse(null);
            if (!Objects.isNull(accLoanVO)) {
                // 客户名称
                loanRepayDetailVO.setCustName(accLoanVO.getCusName());
                // 证件类型
                loanRepayDetailVO.setIdType(accLoanVO.getCertType());
                // 证件号
                loanRepayDetailVO.setIdNo(accLoanVO.getCertCode());
                // 放款金额
                loanRepayDetailVO.setDnAmt(accLoanVO.getLoanAmount());
            }
        }
        if (loanRepayDetailVOS.size() > 0) {
            int num = loanRepayDetailService.insertOrUpdatePsd(loanRepayDetailVOS);
            logger.info("批次时间：[{}]的互金还款记录同步批次执行dueData函数插入或更新还款记录表完成，变更的数据为：[{}]", sub_date_date, num);
        }
        if (diffLogVOS.size() > 0) {
            int num = syncRepayDetailDiffLogService.batchInsert(diffLogVOS);
            logger.info("批次时间：[{}]的互金还款记录同步批次执行dueData函数插入差异表表完成，变更的数据为：[{}]", sub_date_date, num);
        }
        logger.info("批次时间：[{}]的互金还款记录同步批次执行dueData函数结束", sub_date_date);
    }

    private void setSetlType(SynAccRepayPlayDetailVO sedSynAccRepayPlayDetailVO, LoanRepayDetailVO loanRepayDetailVO) throws Exception {
        if ("NS".equals(sedSynAccRepayPlayDetailVO.getSetlTyp()) || "PR".equals(sedSynAccRepayPlayDetailVO.getSetlTyp()) || "PO".equals(sedSynAccRepayPlayDetailVO.getSetlTyp())) {
            //判断还款日期
            LoanRepayPlanVO param = new LoanRepayPlanVO();
            param.setTerm(Integer.valueOf(sedSynAccRepayPlayDetailVO.getRepayTerm()));
            param.setRefNbr(sedSynAccRepayPlayDetailVO.getLoanNo());
            LoanRepayPlanVO loanRepayPlanByRefNbrAndTerm = loanRepayPlanService.getLoanRepayPlanByRefNbrAndTerm(param);
            if (loanRepayPlanByRefNbrAndTerm != null) {
                String endDate = StringUtil.isNullorBank(loanRepayPlanByRefNbrAndTerm.getGraceDate())?loanRepayPlanByRefNbrAndTerm.getStmtDate():loanRepayPlanByRefNbrAndTerm.getGraceDate();
                //判断结束日期和回收日期
                if (TimeUtil.compareDates(endDate,sedSynAccRepayPlayDetailVO.getRetDate())==-1) {
                    //逾期还款
                    loanRepayDetailVO.setSetlTyp(ConsoleConstant.REPAY_TYPE_04);
                    return;
                }
                if (TimeUtil.compareDates(endDate,sedSynAccRepayPlayDetailVO.getRetDate())==0){
                    //逾期还款
                    loanRepayDetailVO.setSetlTyp(ConsoleConstant.REPAY_TYPE_01);
                    return;
                }
            }else {
                if ("0".equals(sedSynAccRepayPlayDetailVO.getRepayTerm()) && "PR".equals(sedSynAccRepayPlayDetailVO.getSetlTyp())){
                    loanRepayDetailVO.setSetlTyp(ConsoleConstant.REPAY_TYPE_02);
                    return;
                }
            }
        }
        loanRepayDetailVO.setSetlTyp(repayType.get(loanRepayDetailVO.getSetlTyp()));
    }

    private LoanRepayDetailVO getByRpyNo(List<LoanRepayDetailVO> list, SynAccRepayPlayDetailVO sedSynAccRepayPlayDetailVO) {
        if (list == null) {
            return null;
        }
        if (list.isEmpty()) {
            return null;
        }
        for (LoanRepayDetailVO loanRepayDetailVO : list) {
            if (loanRepayDetailVO.getRpyNo().equals(sedSynAccRepayPlayDetailVO.getRpyNo())
                    && loanRepayDetailVO.getLoanNo().equals(sedSynAccRepayPlayDetailVO.getLoanNo())
                    && loanRepayDetailVO.getSetlApplyDt().equals(sedSynAccRepayPlayDetailVO.getRetDate())
                    && loanRepayDetailVO.getRepayTerm().equals(sedSynAccRepayPlayDetailVO.getRepayTerm())
            ) {
                return loanRepayDetailVO;
            }
        }
        return null;
    }

    private void insertDiffLog(String diffType, SynAccRepayPlayDetailVO hjRecord, LoanRepayDetailVO wdRecord) {
        SyncRepayDetailDiffLogVO syncRepayDetailDiffLogVO = new SyncRepayDetailDiffLogVO();
        syncRepayDetailDiffLogVO.setId(UUID.randomUUID().toString());
        syncRepayDetailDiffLogVO.setDataType(diffType);
        syncRepayDetailDiffLogVO.setCreateTime(new Date());
        syncRepayDetailDiffLogVO.setBatchRunTime(batchRunDate);
        syncRepayDetailDiffLogVO.setOpenDay(openDay);
        syncRepayDetailDiffLogVO.setBatchDay(batchSubDate);
        syncRepayDetailDiffLogVO.setHjSetlSeq(hjRecord.getRpyNo());
        syncRepayDetailDiffLogVO.setHjLoanNo(hjRecord.getLoanNo());
        syncRepayDetailDiffLogVO.setHjRepayTerm(hjRecord.getRepayTerm());
        syncRepayDetailDiffLogVO.setHjSetlTyp(hjRecord.getSetlTyp());
        syncRepayDetailDiffLogVO.setHjTotalAmt(hjRecord.getTotalAmt());
        syncRepayDetailDiffLogVO.setHjAllOdPrcpAmt(hjRecord.getSetlOdPrcpAmt());
        syncRepayDetailDiffLogVO.setHjAllOdNormIntamt(hjRecord.getSetlOdNormInt());
        syncRepayDetailDiffLogVO.setHjAllOdIntAmt(hjRecord.getSetlOdIntAmt());
        syncRepayDetailDiffLogVO.setHjAllOdCommIntAmt(hjRecord.getSetlOdCommInt());
        syncRepayDetailDiffLogVO.setHjSetlTotalFee(hjRecord.getSetlTotalFee());
        syncRepayDetailDiffLogVO.setHjDisbAcNo(hjRecord.getDisbAcNo());
        syncRepayDetailDiffLogVO.setHjRetDate(hjRecord.getRetDate());
        if (Objects.isNull(wdRecord)) {
            diffLogVOS.add(syncRepayDetailDiffLogVO);
            return;
        }
        syncRepayDetailDiffLogVO.setWdSetlSeq(wdRecord.getSetlSeq());
        syncRepayDetailDiffLogVO.setWdLoanNo(wdRecord.getLoanNo());
        syncRepayDetailDiffLogVO.setWdRepayTerm(wdRecord.getRepayTerm());
        syncRepayDetailDiffLogVO.setWdSetlTyp(wdRecord.getSetlTyp());
        syncRepayDetailDiffLogVO.setWdTotalAmt(wdRecord.getTotalAmt());
        syncRepayDetailDiffLogVO.setWdAllOdPrcpAmt(wdRecord.getSetlOdPrcpAmt());
        syncRepayDetailDiffLogVO.setWdAllOdNormIntAmt(wdRecord.getSetlOdNormInt());
        syncRepayDetailDiffLogVO.setWdAllOdIntAmt(wdRecord.getSetlOdIntAmt());
        syncRepayDetailDiffLogVO.setWdAllOdCommIntAmt(wdRecord.getSetlOdCommInt());
        syncRepayDetailDiffLogVO.setWdSetlTotalFee(wdRecord.getSetlTotalFee());
        syncRepayDetailDiffLogVO.setWdDisbAcNo(wdRecord.getDisbAcNo());
        syncRepayDetailDiffLogVO.setWdSetlApplyDt(wdRecord.getSetlApplyDt());
        syncRepayDetailDiffLogVO.setWdCustName(wdRecord.getCustName());
        syncRepayDetailDiffLogVO.setWdIdType(wdRecord.getIdType());
        syncRepayDetailDiffLogVO.setWdIdNo(wdRecord.getIdNo());
        syncRepayDetailDiffLogVO.setWdDnAmt(wdRecord.getDnAmt());
        syncRepayDetailDiffLogVO.setWdSetlCreateUsr(wdRecord.getSetlCreateUsr());
        syncRepayDetailDiffLogVO.setWdSetlCreateDt(wdRecord.getSetlCreateDt());
        syncRepayDetailDiffLogVO.setWdWfApprSts(wdRecord.getWfApprSts());
        syncRepayDetailDiffLogVO.setWdAllOdFeeAmt(wdRecord.getAllOdFeeAmt());
        syncRepayDetailDiffLogVO.setWdLastChgDt(wdRecord.getLastChgDt());
        syncRepayDetailDiffLogVO.setWdSetlValDt(wdRecord.getSetlValDt());
        //还款号
        syncRepayDetailDiffLogVO.setWdBkCol1(wdRecord.getRpyNo());
        diffLogVOS.add(syncRepayDetailDiffLogVO);
        return;
    }


    private String sedLoanFilePath = "/home/ocmuser/share/infile/psd/syncfile/";

    private String fileNameOfDat = "idl_dm_loan_rcallbk_info_i.$date$.dat";

    private String fileNamOfOk = "idl_dm_loan_rcallbk_info_i.$date$.ok";
}
